using System;
using System.Collections;
using System.Data;
using BO = PHSRAG.Insight21.BusinessObjects;
using Utility = PHSRAG.Utility;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using DataAccess = PHSRAG.Utility.DataAccess;
using System.Data.SqlClient;
using PHSRAG.Insight21.Agreements;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// Summary description for ContinuingReview.
    /// </summary>
    public class ContinuingReview : ProtocolProcess
    {
        public ContinuingReview(ICachePolicy cachePolicy)
            : base(cachePolicy)
        {
            // set the type.
            Type = Constants.ProtocolProcessType.ContinuingReview;
        }

        #region Constructor
        /// <summary>
        /// Constructor for ContinuingReview which takes a data row.
        /// </summary>
        /// <param name="cachePolicy">the prevalent cache policy to use.</param>
        /// <param name="dataRow">a row to construct the object with.</param>
        public ContinuingReview(ICachePolicy cachePolicy, DataRow dataRow)
            : base(cachePolicy, dataRow)
        {
            // set the type.
            Type = Constants.ProtocolProcessType.ContinuingReview;
        }
        #endregion

        /// <summary>
        /// Override the Approve method, but only do things differently if it's an Animals TR or AR.
        /// </summary>
        /// <param name="insightTransaction"></param>
        /// <param name="rexTtransaction"></param>
        /// <param name="insightConnectionString"></param>
        /// <param name="rexConnectionString"></param>
        /// <param name="parentProtocol"></param>
        public override void Approve(SqlTransaction insightTransaction, SqlTransaction rexTransaction, string insightConnectionString, string rexConnectionString, Protocol parentProtocol)
        {
            base.Approve(insightTransaction, rexTransaction, insightConnectionString, rexConnectionString, parentProtocol);

            // Approval Script sets number of animals to the totnumanimals question
            RunApprovalScript();

            if (this.Type == Humans.Constants.AnimalProtocolProcessType.TriennialReview ||
                 this.Type == Humans.Constants.AnimalProtocolProcessType.AnnualReview)
            {
                // run Animals IR submission script
                // move over any Hazard agents in Rex for both AR and TR 
                // since those are what can be updated. Note that we don't want to 
                // delete all of them in Rex, just update existing ones or insert 
                // new records. Hence the lookups...
                // ALSO NOTE: any bug fixes here must also be made in the Application.Submit 
                // ALSO NOTE: we're running the submission script for Animals IR Here (rather than duplicate
                // that code in two places.) IF/when we get to creating callable script functions,
                // well remove this and put it in one spot.
                #region Run IR Submission script
                Protocol parentProt = new Protocol(CachePolicy);
                parentProt.Load(insightConnectionString, this.ProtocolId);


                string submissionScriptType = (string)ScriptEngine.Constants.ScriptType.AnimalSubmissionInitialReveiew;
                AnimalsRexParams rexParameters = new AnimalsRexParams();


                ArrayList scripts = ScriptEngine.Script.GetScriptsByType(insightConnectionString,
                    submissionScriptType, CachePolicy);

                ScriptEngine.Script submissionScript = null;

                if (scripts.Count > 0)
                    submissionScript = (ScriptEngine.Script)scripts[0];

                ProtocolVersion currentVersion = GetLatestProtocolVersion(insightConnectionString,
                           false, CachePolicy) as ProtocolVersion;

                if (submissionScript != null)
                {
                    using (ScriptEngine.ScriptEngineHost scriptHost =
                   new PHSRAG.Insight21.ScriptEngine.ScriptEngineHost(
                              ScriptEngine.Constants.RootMoniker.SubmissionScriptMoniker,
                              ScriptEngine.Constants.RootNamespaces.SubmissionScript,
                              true))
                    {
                        ArrayList refs = ScriptEngine.ScriptReference.GetAllScriptReferences(
                            insightConnectionString);

                        DirectoryInfo directoryInfo = new DirectoryInfo(System.IO.Path.GetDirectoryName(
                                (new Regex(@"^file:/+")).Replace(Assembly.GetExecutingAssembly().CodeBase, string.Empty)));

                        string executingAssemblyPath = string.Format("{0}\\", directoryInfo.FullName);

                        for (int i = 0; i < refs.Count; ++i)
                        {
                            ScriptEngine.ScriptReference reference = (ScriptEngine.ScriptReference)refs[i];
                            scriptHost.AddDLLReference(string.Format("{0}\\{1}", executingAssemblyPath, reference.Name));
                        }

                        // add the connection string
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ConnectionString,
                            insightConnectionString);

                        // add the Process
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolProcss,
                            this);

                        if (currentVersion == null)
                        {
                            throw new Exception("No protocol version found");
                        }
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolVersion, currentVersion);


                        // add the RexParams
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.RexParams, rexParameters);

                        // add the caching policy
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.CachePolicy, CachePolicy);

                        // compile and run the script.
                        if (scriptHost.Compile(submissionScript))
                            scriptHost.RunScript(submissionScript,
                                ScriptEngine.Constants.AssemblyType.SubmissionScript,
                                ScriptEngine.Constants.MethodsToRun.Main);
                    }
                }
                #endregion

                // now get the data, and update Rex.
                #region Hazardous Agents
                if (rexParameters.HazardousAgents.Count > 0)
                {
                    CDS.RefCodes refCodes = new PHSRAG.Insight21.CDS.RefCodes(CachePolicy);
                    refCodes.Load(insightConnectionString, null);
                    
                    // get the latest Rex document ID
                    if (parentProt.RexProtocolId != 0)
                    {
                        parentProt.RexProtocolId = GetCurrentRexProtocolId(rexConnectionString, null, parentProt.ProtocolNumber, Constants.ModuleType.Animals);
                    }


                    for (int i = 0; i < rexParameters.HazardousAgents.Count; i++)
                    {
                        Humans.AnimalsRexParams.HazardousAgent hazAgent = (Humans.AnimalsRexParams.HazardousAgent)rexParameters.HazardousAgents[i];

                        string hazardAgentType;
                        string hazardName;

                        if (hazAgent.HazardType == "Rad")
                        {
                            hazardAgentType = "Radioisotope";
                            // look up the ref code
                            CDS.RefCode isotope = refCodes.GetRefCode(hazAgent.Isotope);
                            hazardName = isotope.Meaning;
                        }
                        else if (hazAgent.HazardType == "Chem")
                        {
                            hazardAgentType = "Toxic Chemical/Carcinogen";
                            // look up the ref code
                            CDS.RefCode chemAgent = refCodes.GetRefCode(hazAgent.Chemical);
                            hazardName = chemAgent.Meaning;
                        }
                        else if (hazAgent.HazardType == "Bio")
                        {
                            hazardAgentType = "Biological Agent";
                            // look up the ref code
                            CDS.RefCode biologicalAgent = refCodes.GetRefCode(hazAgent.BioAgent);
                            hazardName = biologicalAgent.Meaning;
                        }
                        else
                        {
                            hazardAgentType = "Radioisotope";
                            hazardName = hazAgent.Isotope;
                        }

                        int detailID = 0;
                        DataSet hazardAgs = Utility.DataAccess.GetDataSet(rexTransaction.Connection, rexTransaction,
                            "spAnimalHazardGet",
                            Utility.DataAccess.BuildSqlParameterArray(
                            "@nAnimalProtID", SqlDbType.Int, parentProtocol.RexProtocolId,
                            "@sHazardAgentType", SqlDbType.VarChar, hazardAgentType));

                        if (hazardAgs.Tables[0] != null && hazardAgs.Tables[0].Rows.Count > 0)
                        {
                            for (int q = 0; q < hazardAgs.Tables[0].Rows.Count; q++)
                            {
                                detailID = (int)hazardAgs.Tables[0].Rows[q]["nAnimalProtHazardID"];
                            }
                        }


                        // lookup the AnimalHazardAgent ID
                        DataSet hazardIDs = Utility.DataAccess.GetDataSet(rexTransaction.Connection, rexTransaction,
                            "spAnimalHazardAgentIDGet",
                            Utility.DataAccess.BuildSqlParameterArray(
                            "@sAgentName", SqlDbType.VarChar, hazardName));

                        int hazAgentID = 0;
                        if (hazardIDs.Tables[0].Rows.Count > 0)
                        {
                            for (int y = 0; y < hazardIDs.Tables[0].Rows.Count; y++)
                            {
                                hazAgentID = (int)hazardIDs.Tables[0].Rows[y]["nHazardAgentId"];
                            }
                        }

                        string building = string.Empty;

                        if (hazAgent.Building.Count > 0)
                            building = (string)hazAgent.Building[0];

                        Utility.DataAccess.ExecuteNonQuery(rexTransaction.Connection, rexTransaction,
                            "spAnimalHazardUpdate",
                            Utility.DataAccess.BuildSqlParameterArray(
                            "@nAnimalProtHazardID", SqlDbType.Int, detailID,
                            "@nAnimalProtID", SqlDbType.Int, parentProtocol.RexProtocolId,
                            "@sHazardAgentType", SqlDbType.VarChar, hazardAgentType,
                            "@sHazardAgentName", SqlDbType.VarChar, hazardName,
                            "@nHazardAgentID", SqlDbType.Int, hazAgentID,
                            "@sRadioMicroCiPerAnimal", SqlDbType.VarChar, hazAgent.Dose,
                            "@sRadioisotopePermit", SqlDbType.VarChar, hazAgent.PermitNum,
                            "@sRadioisotopePermitHolder", SqlDbType.VarChar, hazAgent.PermitName,
                            "@sDose", SqlDbType.VarChar, hazAgent.Dose,
                            "@sFrequency", SqlDbType.VarChar, hazAgent.Frequency,
                            "@sTotalDoses", SqlDbType.VarChar, hazAgent.TotalDoses,
                            "@sMethod", SqlDbType.VarChar, hazAgent.Route,
                            "@sDuration", SqlDbType.VarChar, hazAgent.Duration,
                            "@sBuilding", SqlDbType.VarChar, building,
                            "@sRoom", SqlDbType.VarChar, hazAgent.Room,
                            "@sManipulations", SqlDbType.VarChar, hazAgent.Manipulations,
                            "@sSafetyComments", SqlDbType.VarChar, DBNull.Value));
                    }


                }
                #endregion


                #region Merge the Form changes into the Insight top attachmentTitle.
                ProtocolVersion latestIRVersion = Protocol.GetLatestApplicationVersion(
                        ProtocolId,
                        insightConnectionString, false,
                        CachePolicy);

                // preload these because we run into DB Blocking issues with the way this is done
                // if we call this later on in the method. 
                ArrayList staff = this.StudyStaff;
                ArrayList protocolStaff = this.Protocol.StudyStaffList;

                if (latestIRVersion != null)
                {
                    ProtocolProcess IR = null;
                    foreach (ProtocolProcess currProcess in parentProt.ProtocolProcesses)
                    {
                        if (currProcess.Type == Humans.Constants.AnimalProtocolProcessType.InitialReview)
                        {
                            IR = currProcess;
                            break;
                        }
                    }
                    // if it's still null, load it.
                    if (IR == null)
                    {
                        IR = ProtocolProcess.GetProtocolProcess(
                            insightConnectionString,
                            latestIRVersion.ProtocolProcessId,
                            CachePolicy,
                            null);
                    }


                    //ProtocolVersion newVersion = IR.AddNewVersion( CachePolicy );
                    ProtocolVersion newVersion = IR.GetLatestProtocolVersion(false, CachePolicy).Clone();
                    newVersion.QuestionnaireAnswers.RemoveRange(0, newVersion.QuestionnaireAnswers.Count);

                    if (IR != null)
                    {
                        IR.ProtocolVersions.Add(newVersion);

                        if (this.Type == Humans.Constants.AnimalProtocolProcessType.TriennialReview)
                        {
                            // merge the staff on teh IR.
                            foreach (StaffPerson origStaff in IR.StudyStaff)
                            {
                                if (origStaff.RemovedProtocolProcessId == this.Id)
                                {
                                    //origStaff.IsCurrent = false;
                                    //origStaff.Save(insightTransaction);

                                    //delete the record completely. if removedppid is not set to 0 before calling delete
                                    //then protocolstaff_map record is not deleted
                                    //and when the approve method calls submit on the latest IR, the study staff list loaded will also contain
                                    //the staff deleted by the amendment and when this latest IR is saved, the deleted staff is again given access
                                    //(record inserted into FwkResource_DomainUser_Map) with permission level set to 0
                                    origStaff.RemovedProtocolProcessId = 0;
                                    origStaff.Delete(insightTransaction);
                                }
                            }

                            // NULL the collection, now that it's been saved
                            // since we'll reuse this collection when updating Rex- it won't know
                            // that we marked this one current. Rather than check the Current flag 
                            // when updating Rex, it's better to reload the collection altogether.
                            IR.StudyStaff = null;
                        }
                    }

                    foreach (FormsManagement.QuestionnaireAnswer amendQA in currentVersion.QuestionnaireAnswers)
                    {
                        if (amendQA.Action != (int)FormsManagement.QuestionnaireAnswer.UserAction.Remove
                                && (amendQA.QuestionnaireVersion.Questionnaire.Type != FormsManagement.Constants.QuestionnaireType.Amendment
                                || amendQA.QuestionnaireVersion.Questionnaire.Type != "QUESTCAT_ANM_AM"))
                            newVersion.QuestionnaireAnswers.Add(amendQA.Clone(false));
                    }

                    foreach (FormsManagement.QuestionnaireAnswer initialRevQA in latestIRVersion.QuestionnaireAnswers)
                    {
                        int currQuestionnaireId = initialRevQA.QuestionnaireVersion.QuestionnaireID;
                        bool foundQA = false;
                        foreach (FormsManagement.QuestionnaireAnswer newCopiedQA in newVersion.QuestionnaireAnswers)
                        {
                            if (currQuestionnaireId == newCopiedQA.QuestionnaireVersion.QuestionnaireID)
                            {
                                foundQA = true;
                                break;
                            }
                        }

                        if (!foundQA)
                        {
                            newVersion.QuestionnaireAnswers.Add(initialRevQA.Clone(false));
                        }
                    }
                    IR.Save(insightTransaction);
                }
                else if (this.Type == Constants.AnimalProtocolProcessType.TriennialReview)
                {
                    // legacy protocol that has run a triennial review, create an IR for it.
                    ProtocolProcess newIRProcess = new ProtocolProcess(CachePolicy);
                    newIRProcess.Type = Constants.AnimalProtocolProcessType.InitialReview;
                    newIRProcess.Name = Constants.AnimalProtocolProcessShortType.InitialReview;
                    newIRProcess.ProtocolId = this.ProtocolId;
                    newIRProcess.SubmitterId = this.SubmitterId;
                    newIRProcess.SubmittedDate = this.SubmittedDate;
                    newIRProcess.LastModifiedByUserId = this.LastModifiedByUserId;
                    newIRProcess.LastModifiedDate = this.LastModifiedDate;
                    newIRProcess.Locked = this.Locked;
                    newIRProcess.LastLockedVersion = 1;
                    newIRProcess.Status = this.Status;
                    newIRProcess.Save(insightConnectionString);

                    latestIRVersion = this.GetLatestProtocolVersion(false, CachePolicy).Clone();
                    latestIRVersion.Version = 1;
                    latestIRVersion.Status = Humans.Constants.ProtocolProcessStatus.ApprovedInitialApp;
                    latestIRVersion.LockDate = latestIRVersion.CreateDate;
                    latestIRVersion.ProtocolProcessId = newIRProcess.Id;
                    newIRProcess.ProtocolVersions.Add(latestIRVersion);
                }
                #endregion

                if (this.Type == Humans.Constants.AnimalProtocolProcessType.TriennialReview)
                {
                    // merge the staff
			        ArrayList removedStaffList = new ArrayList();
                    foreach (StaffPerson amendStaff in staff)
                    {
                        if (amendStaff.AddedProtocolProcessId == Id)
                        {
                            amendStaff.IsCurrent = true;

                            // update the PI if it has changed.
                            if (amendStaff.RoleId == Humans.Constants.StaffRoleType.PrincipalInvestigator)
                            {
                                this.Protocol.PIPersonId = amendStaff.AdmPersonId;
                            }
                        }
				        if (amendStaff.RemovedProtocolProcessId == Id)
				        {
					        //amendStaff.IsCurrent = false;
					        amendStaff.RemovedProtocolProcessId = 0;
					        amendStaff.Delete(insightTransaction);
					        removedStaffList.Add(amendStaff);
				        }
                    }
			        //remove the deleted staff from collection
			        foreach (StaffPerson removedStaff in removedStaffList)
				        staff.Remove(removedStaff);

			        removedStaffList = new ArrayList();
                    foreach (StaffPerson origStaff in protocolStaff)
                    {
                        if (origStaff.RemovedProtocolProcessId == this.Id)
                        {
                            //origStaff.IsCurrent = false;
                            //origStaff.Save(insightTransaction);
					        origStaff.RemovedProtocolProcessId = 0;
					        origStaff.Delete(insightTransaction);
					        removedStaffList.Add(origStaff);
                        }
                    }
			        //remove the deleted staff from collection
			        foreach (StaffPerson removedStaff in removedStaffList)
				        protocolStaff.Remove(removedStaff);

                    if (latestIRVersion != null)
                        latestIRVersion.Save(insightTransaction);


                    this.Protocol.Save(insightTransaction);
                    Save(insightTransaction);
                }
            }
        }

        /// <summary>
        /// This overridden method sets Added Protocol Process ID, Protocol ID and sets current flag to true.
        /// StudyStaff object gets saved after changes.		
        /// </summary>
        /// <param name="StaffPerson">StaffPerson Object</param>
        public override void AddStudyStaff(StaffPerson staffPerson)
        {
            try
            {
                staffPerson.AddedProtocolProcessId = Id;
                staffPerson.ProtocolId = ProtocolId;
                staffPerson.IsCurrent = false;
                StudyStaff.Add(staffPerson);
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog(
                    "Failed to add study staff in Amendment", ex, true, Utility.ExceptionReport.ReportType.Error);
                throw new Exception("Failed to add study staff in Amendment", ex);
            }

        }

        /// <summary>
        /// This overridden method sets Removed Protocol Process ID, and sets current flag to false.
        /// StudyStaff object gets saved after changes.
        /// </summary>
        /// <param name="connectionString">connection to the DB.</param>
        /// <param name="StaffPerson">StaffPerson Object</param>
        public override void RemoveStudyStaff(string connectionString, StaffPerson staffPerson)
        {
            try
            {
                staffPerson.RemovedProtocolProcessId = Id;
                staffPerson.Save(connectionString);
                StudyStaff.Remove(staffPerson);
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog(
                    "Failed to remove study staff in Amendment", ex, true, Utility.ExceptionReport.ReportType.Error);
                throw new Exception("Failed to remove study staff in Amendment", ex);
            }
        }

        public override void Submit(ICachePolicy cachePolicy, string insightConnectionString, string rexConnectionString, string executingAssemblyPath, RexParams rexParameters,
                            bool IsRelocked)
        {
            base.Submit(cachePolicy, insightConnectionString, rexConnectionString, executingAssemblyPath, rexParameters, IsRelocked);

            Protocol currProtocol = new Protocol(cachePolicy);
            currProtocol.Load(insightConnectionString, this.ProtocolId);

            if (currProtocol.ModuleType == Constants.ModuleType.Animals)
            {
                // if the ID isn't zero, look it up to see if
                // what we have is the current attachmentTitle # (in case it's
                // been cloned in Rex bc of Amendment or Correction)
                if (currProtocol.RexProtocolId != 0)
                {
                    currProtocol.RexProtocolId = base.GetCurrentRexProtocolId(rexConnectionString, null, currProtocol.ProtocolNumber, Constants.ModuleType.Animals);
                    currProtocol.Save(insightConnectionString);
                }

                string annReviewType = string.Empty;
                if (this.Type == Humans.Constants.AnimalProtocolProcessType.AnnualReview)
                {
                    annReviewType = "Annual Review";
                }
                else if (this.Type == Humans.Constants.AnimalProtocolProcessType.TriennialReview)
                {
                    annReviewType = "Triennial Review";
                }

				int periodID;
                int rexProtId = currProtocol.RexProtocolId;
                SqlConnection rexConn = new SqlConnection(rexConnectionString);
                rexConn.Open();
                SqlTransaction rexTrans = rexConn.BeginTransaction();

                try
                {
                    // call the new updated SP here...
                    DataSet results = GetLatestAnimalsRexProcessData(currProtocol.ProtocolNumber, rexTrans);

					ReceivedDate = DateTime.Now;

					if (results.Tables[0].Rows.Count > 0)
					{
						object o = results.Tables[0].Rows[0]["dtReceived"];
						this.ReceivedDate = (o == DBNull.Value) ? DateTime.MinValue : (DateTime)o;

						o = results.Tables[0].Rows[0]["nStatusId"];
						if ((int)o != 0)
							this.RexIRBStatusId = (int)o;

						o = results.Tables[0].Rows[0]["nAnimalProtId"];
						if ((int)o > 0 && (int)o != rexProtId)
							currProtocol.RexProtocolId = (int)o;

						o = results.Tables[0].Rows[0]["nPeriod"];
						periodID = (int)o;
					}
					else
					{
						// calculate the PeriodID to pass in here... Fun.
						periodID = Convert.ToInt32(Utility.DataAccess.ExecuteScalar(rexConnectionString,
								"spAnimalAnnualReviewGetNewPeriod",
								Utility.DataAccess.BuildSqlParameterArray(
								"@nAnimalProtID", SqlDbType.Int, currProtocol.RexProtocolId,
								"@sAnnReviewType", SqlDbType.VarChar, annReviewType)));

					}

                    // now use the RexParams here to add any Components to be Changed.for 
                    this.RexIRBStatusId = Convert.ToInt32(Utility.DataAccess.ExecuteScalar(rexConn, rexTrans,
                     "spAnimalAnnualReviewUpdate",
                     Utility.DataAccess.BuildSqlParameterArray(
                     "@nAnimalProtId", SqlDbType.Int, currProtocol.RexProtocolId,
                     "@nAnnualReviewID", SqlDbType.Int, this.RexIRBStatusId,
                     "@nPeriod", SqlDbType.Int, periodID,
                     "@dtReceived", SqlDbType.DateTime, (this.ReceivedDate == DateTime.MinValue) ? (object)DBNull.Value : (object)this.ReceivedDate,
                     "@sProjectStatus", SqlDbType.VarChar, (rexParameters as AnimalsRexParams).ProjectStatus,
                     "@dtClosed", SqlDbType.DateTime, ((rexParameters as AnimalsRexParams).DateClosed == DateTime.MinValue) ? (object)DBNull.Value : (object)(rexParameters as AnimalsRexParams).DateClosed,
                     "@nAnimalsOrdered", SqlDbType.Int, (rexParameters as AnimalsRexParams).AnimalsOrdered,
                     "@nAnimalsReported", SqlDbType.Int, (rexParameters as AnimalsRexParams).AnimalsReported,
                     "@nAdultsOrdered", SqlDbType.Int, (rexParameters as AnimalsRexParams).AdultsOrdered,
                     "@nAdultsReported", SqlDbType.Int, (rexParameters as AnimalsRexParams).AdultsReported,
                     "@nFemaleLitterOrdered", SqlDbType.Int, (rexParameters as AnimalsRexParams).FemaleLitterOrdered,
                     "@nFemaleLitterReported", SqlDbType.Int, (rexParameters as AnimalsRexParams).FemaleLitterReported,
                     "@nGeneratedReported", SqlDbType.Int, (rexParameters as AnimalsRexParams).GeneratedReported,
                     "@nOtherOrdered", SqlDbType.Int, (rexParameters as AnimalsRexParams).OtherOrdered,
                     "@nOtherReported", SqlDbType.Int, (rexParameters as AnimalsRexParams).OtherReported,
                     "@bCurrentStatus", SqlDbType.Bit, true,
                     "@nProtocolProcessId", SqlDbType.Int, this.Id)));

                    // Notes...
                    if ((rexParameters as AnimalsRexParams).AnnReviewNotes != "" &&
                        (rexParameters as AnimalsRexParams).AnnReviewNotes != null &&
                        (rexParameters as AnimalsRexParams).AnnReviewNotes != string.Empty)
                    {
                        // spAnimalNoteUpdate
                        Utility.DataAccess.ExecuteNonQuery(rexConn, rexTrans,
                            "spAnimalNoteUpdate",
                            Utility.DataAccess.BuildSqlParameterArray(
                            "@nAnimalProtId", SqlDbType.Int, currProtocol.RexProtocolId,
                            "@sNote", SqlDbType.Text, (rexParameters as AnimalsRexParams).AnnReviewNotes,
                            "@sRTFNote", SqlDbType.Text, (rexParameters as AnimalsRexParams).AnnReviewNotes));
                    }

                    this.Save(insightConnectionString);

                    rexTrans.Commit();
                }
                catch
                {
                    rexTrans.Rollback();
                    throw;
                }
                finally
                {
                    if (rexConn.State != ConnectionState.Closed)
                        rexConn.Close();
                }
            }
            else
            {
                SqlConnection rexConn = new SqlConnection(rexConnectionString);
                rexConn.Open();
                SqlTransaction rexTransaction = rexConn.BeginTransaction();

                try
                {
                    #region Races
                    if (rexParameters.CRRaces.Count > 0)
                    {
                        // delete all drugs for this protocol, then re-add them.
                        Utility.DataAccess.ExecuteNonQuery(rexTransaction.Connection, rexTransaction,
                            "spIRBStatusAnnEnrollDelete",
                            Utility.DataAccess.BuildSqlParameterArray(
                            "@nIRBProtocolID", SqlDbType.Int, currProtocol.RexProtocolId,
                            "@nStatusID", SqlDbType.Int, RexIRBStatusId));

                        // Delete and re-add Races.
                        for (int i = 0; i < rexParameters.CRRaces.Count; i++)
                        {
                            Humans.RexParams.CRRace crRace = (Humans.RexParams.CRRace)rexParameters.CRRaces[i];

                            Utility.DataAccess.ExecuteNonQuery(rexTransaction.Connection, rexTransaction,
                                "spIRBDrugsBiologicUpdate",
                                Utility.DataAccess.BuildSqlParameterArray(
                                "@nIRBProtocolID", SqlDbType.Int, currProtocol.RexProtocolId,
                                "@nStatusID", SqlDbType.Int, RexIRBStatusId,
                                "@sRace", SqlDbType.VarChar, crRace.Race,
                                "@nMales", SqlDbType.Int, crRace.Males,
                                "@nFemales", SqlDbType.Int, crRace.Females,
                                "@nUnknown", SqlDbType.Int, crRace.Unknown));
                        }
                    }
                    #endregion
                }
                catch
                {
                    rexTransaction.Rollback();
                    throw;
                }
                finally
                {
                    if (rexConn.State != ConnectionState.Closed)
                        rexConn.Close();
                }
            }
        }

        #region Overridden Methods
        /// <summary>
        /// This method returns the required study staff to be displayed
        /// in the View Application (currently a PDF) which is all the
        /// current protocol staff plus any added specifically for this process.
        /// </summary>
        /// <returns>ArrayList containing StudyStaff</returns>
        public override ArrayList GetStudyStaffForViewApp()
        {
            return StudyStaff;
        }

        /// <summary>
        /// This method returns the required attachments to be displayed
        /// in the View Application (currently a PDF) which is all the
        /// current attachments plus any added specifically for this process.
        /// </summary>
        /// <returns>ArrayList of ProtocolDocuments</returns>
        //public override ArrayList GetProtocolDocumentsForViewApp()
        //{
        //    return ProtocolDocuments;
        //}
        #endregion

    }
}
